package easier.app.x.view;

import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.annotation.SuppressLint;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.view.animation.DecelerateInterpolator;

/**
 * 辅助View提供拖拽移动能力
 */
public class DragMoveTouchListener implements OnTouchListener {

    private static final int MIN_TOUCH_SLOP = 20;

    private final View mView;

    private int parentHeight;
    private int parentWidth;
    private int lastX;
    private int lastY;
    private boolean isDrag;

    private AnimatorUpdateListener mAnimatorUpdateListener;
    private int mLeftRight = 1;

    /* 手指抬起时是否只靠右边 */
    private boolean isAlignRight;

    /* 辅助判断滑动结束后是否触发点击事件 */
    private int movedX;
    private int movedY;
    //private final Runnable action = new Action();

    public DragMoveTouchListener( View view ) {

        mView = view;
    }

    public void setAlignRight( boolean alignRight ) {

        isAlignRight = alignRight;
    }

    public void setAnimatorUpdateListener( AnimatorUpdateListener animatorUpdateListener ) {

        mAnimatorUpdateListener = animatorUpdateListener;
    }

    public int getLeftRight() {

        return mLeftRight;
    }

    private boolean isDrag() {

        return isDrag || (mView.getX() != 0 && (mView.getX() != parentWidth - mView.getWidth()));
    }

    @SuppressLint( "ClickableViewAccessibility" )
    @Override
    public boolean onTouch( View v, MotionEvent event ) {

        mView.getParent().requestDisallowInterceptTouchEvent( true );

        int rawX = (int) event.getRawX();
        int rawY = (int) event.getRawY();
        switch ( event.getAction() & MotionEvent.ACTION_MASK ) {
            case MotionEvent.ACTION_DOWN:
                mView.setPressed( true );
                isDrag = false;

                movedX = movedY = 0;

                lastX = rawX;
                lastY = rawY;
                ViewGroup parent;
                if ( mView.getParent() != null ) {
                    parent = (ViewGroup) mView.getParent();
                    parentHeight = parent.getMeasuredHeight();
                    parentWidth = parent.getMeasuredWidth();
                }
                return true;
            //break;
            case MotionEvent.ACTION_MOVE:
                if ( parentHeight <= 0 || parentWidth == 0 ) {
                    isDrag = false;
                    break;
                } else {
                    isDrag = true;
                }
                int dx = rawX - lastX;
                int dy = rawY - lastY;

                //这里修复一些华为手机无法触发点击事件
                int distance = (int) Math.sqrt( dx * dx + dy * dy );
                if ( distance == 0 ) {
                    isDrag = false;
                    break;
                }

                movedX += dx;
                movedY += dy;

                float x = mView.getX() + dx;
                float y = mView.getY() + dy;
                //检测是否到达边缘 左上右下
                x = x < 0 ? 0 : x > parentWidth - mView.getMeasuredWidth() ? parentWidth - mView.getMeasuredWidth() : x;
                y = mView.getY() < 0 ? 0
                    : mView.getY() + mView.getMeasuredHeight() > parentHeight ? parentHeight - mView.getMeasuredHeight() : y;
                mView.setX( x );
                mView.setY( y );
                lastX = rawX;
                lastY = rawY;
                break;
            case MotionEvent.ACTION_UP:
                if ( isDrag() ) {
                    //恢复按压效果
                    mView.setPressed( false );
                    if ( rawX >= parentWidth / 2 ) {
                        mLeftRight = 1;
                        //靠右吸附
                        mView.animate().setInterpolator( new DecelerateInterpolator() )
                            .setUpdateListener( mAnimatorUpdateListener )
                            .setDuration( 300 )
                            .x( parentWidth - mView.getWidth() )
                            //.withEndAction( action )
                            .start();
                    } else {
                        mLeftRight = 0;

                        if ( isAlignRight ) {
                            //靠右吸附
                            mView.animate().setInterpolator( new DecelerateInterpolator() )
                                .setUpdateListener( mAnimatorUpdateListener )
                                .setDuration( 300 )
                                .x( parentWidth - mView.getWidth() )
                                //.withEndAction( action )
                                .start();
                        } else {
                            //靠左吸附
                            mView.animate().setInterpolator( new DecelerateInterpolator() )
                                .setUpdateListener( mAnimatorUpdateListener )
                                .setDuration( 300 )
                                .x( 0 )
                                //.withEndAction( action )
                                .start();
                        }
                    }
                }
                if ( Math.abs( movedX ) < MIN_TOUCH_SLOP && Math.abs( movedY ) < MIN_TOUCH_SLOP ) {
                    mView.performClick();
                    movedX = movedY = 0;
                }
                break;
            default:
                break;
        }
        //如果是拖拽则消s耗事件，否则正常传递即可。
        return true;
    }

    /**
     * 辅助判断滑动事件还是点击事件
     */
    private class Action implements Runnable {

        @Override
        public void run() {

            if ( Math.abs( movedX ) < MIN_TOUCH_SLOP && Math.abs( movedY ) < MIN_TOUCH_SLOP ) {
                mView.performClick();
                movedX = movedY = 0;
            }
        }
    }
}
